﻿using Core.DataAccess.Model;
using Core.Framework;
using Dapper;
using Grain.Interfaces;
using Grain.State.StateEntitys;
using iTool.ClusterComponent;
using Orleans;
using System;
using System.Threading.Tasks;

namespace Grain.Implements
{
    public class NotifyService : iToolServiceProducerBase<NotifyServiceStateStorgeProvider>, INotifyService
    {
        private IDBFactory iDBFactory;

        public NotifyService(IDBFactory iDBFactory) : base(AppSetting.QueueConnectorStreamNamespace)
        {
            this.iDBFactory = iDBFactory;
        }


        public async Task Publish(string message, string sendOfChannel)
        {
            var receiveChannel = this.GetPrimaryKeyString();

            // 先判断是否在线，在线在发送
            // 这里应该使用Topic 暂时先这样。 后面重新梳理
            var iReceiveChannel = this.GrainFactory.GetGrain<IChannelService>(receiveChannel);

            var notifyMessage = new DBNotifyMessage();
            notifyMessage.sendChannel = sendOfChannel;
            notifyMessage.reciveChannel = this.GetPrimaryKeyString();
            notifyMessage.content = message;
            notifyMessage.status = await iReceiveChannel.IsInChannel(sendOfChannel) ? 1 : 0;
            notifyMessage.createTime = DateTime.Now;

            var isSystem = message.StartsWith("{\"type\":\"system\"");

            // 消息入库
            using (var db = this.iDBFactory.Create(DatabaseType.Message))
            {
                notifyMessage.id = db.Insert(notifyMessage) ?? 0;
            }

            string sendParameter, receiveParameter;

            var iSendChannel = this.GrainFactory.GetGrain<IChannelService>(sendOfChannel);
            sendParameter = await iSendChannel.GetChannelInfo();


            receiveParameter = await iReceiveChannel.GetChannelInfo();

            // 只有一个人订阅
            if (this.State.Channels.Count == 1)
            {

                if (await iReceiveChannel.IsOnline())
                {
                    await this.SendMessageAsync(new { Topic = receiveChannel, Body = message, SendOfChannel = sendOfChannel, id = notifyMessage.id }.TryToJson());
                }

                if ("edit_functions" == receiveChannel)
                    return;

                await iReceiveChannel.ReceiveMessageEvent(message, sendOfChannel, sendParameter);
            }
            // 多人订阅
            else if (this.State.Channels.Count > 1)
            {
                // 直接发送
                await this.SendMessageAsync(new { Topic = receiveChannel, Body = message, SendOfChannel = sendOfChannel, id = notifyMessage.id }.TryToJson());

                if ("edit_functions" == receiveChannel)
                    return;

                // 然后更新他们的会话（群组会话列表构建需要策略）
                foreach (var item in this.State.Channels)
                {
                    // channel 会话修改
                    var iChannel = this.GrainFactory.GetGrain<IChannelService>(item);
                    await iChannel.ReceiveMessageEvent(message, sendOfChannel, sendParameter);
                }
            }
            else
            {
                // channel 会话修改 !!!!!!!!!! 这里需要修改2个人的会话， 接收方和发送方
                await iReceiveChannel.ReceiveMessageEvent(message, sendOfChannel, sendParameter);
            }

            if (!isSystem)
            {
                await iSendChannel.SendMessageEvent(message, receiveChannel, receiveParameter);
            }

        }

        public async Task PublishSilence(string SendOfChannel, string message)
        {
            var receiveChannel = this.GetPrimaryKeyString();
            var iReceiveChannel = this.GrainFactory.GetGrain<IChannelService>(receiveChannel);
            if (await iReceiveChannel.IsOnline())
            {
                await this.SendMessageAsync(new { Topic = receiveChannel, Body = message, SendOfChannel = SendOfChannel, id = 0 }.TryToJson());
            }
        }

        public async Task Subscribe(string channel)
        {
            if (!this.State.Channels.Contains(channel))
            {
                this.State.Channels.Add(channel);
            }

            await this.WriteStateAsync();
        }

        public async Task UnSubscribe(string channel)
        {
            if (this.State.Channels.Contains(channel))
            {
                this.State.Channels.Remove(channel);
                await this.WriteStateAsync();
            }
        }

        public async Task Clear()
        {
            await this.ClearStateAsync();
        }
    }
}
